package cn.numeron.common.extension

import cn.numeron.common.utility.DateDeserializer
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.reflect.TypeToken
import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonToken
import java.text.DateFormat
import java.util.*

object GsonHelper {
    val gson: Gson by lazy(LazyThreadSafetyMode.SYNCHRONIZED) {
        GsonBuilder()
            .registerTypeAdapter(Date::class.java, DateDeserializer())
            .setDateFormat(DEFAULT_DATETIME_PATTERN)
            .setDateFormat(DateFormat.LONG)
            .create()
    }
}

inline fun <reified T> String.deserialize(): T {
    return GsonHelper.gson.fromJson(this, object : TypeToken<T>() {}.type)
}

inline fun <reified T> T.serialize(): String {
    return GsonHelper.gson.toJson(this)
}

fun JsonReader.nextStringOrNull(): String? {
    return if (peek() == JsonToken.NULL) {
        nextNull()
        null
    } else nextString()
}

fun JsonReader.nextIntOrNull(): Int? {
    return if (peek() == JsonToken.NULL) {
        nextNull()
        null
    } else nextInt()
}

fun JsonReader.nextDoubleOrNull(): Double? {
    return if (peek() == JsonToken.NULL) {
        nextNull()
        null
    } else nextDouble()
}

fun <T> JsonReader.readList(reader: (JsonReader) -> T): List<T> {
    val list = mutableListOf<T>()
    beginArray()
    while (hasNext()) {
        val entity = reader(this)
        list.add(entity)
    }
    endArray()
    return list
}